﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

#region

using System.Globalization;

#endregion

namespace Neto.Extensions;

/// <summary>
///     DateTime 扩展
/// </summary>
public static class DateTimeExtensions
{
    /// <summary>
    ///     返回格式为 (yyyy-MM-dd HH:mm:ss) 的时间字符串
    /// </summary>
    /// <param name="dt">要格式化的 DateTime 对象</param>
    /// <returns>格式化后的时间字符串</returns>
    public static string ToStringLongDate(this DateTime dt)
    {
        return dt.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
    }

    /// <summary>
    ///     返回格式为 (yyyy-MM-dd HH:mm:ss) 的时间字符串
    /// </summary>
    /// <param name="dt">要格式化的 DateTime? 对象</param>
    /// <returns>格式化后的时间字符串，如果为空则返回空字符串</returns>
    public static string ToStringLongDate(this DateTime? dt)
    {
        return dt?.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) ?? string.Empty;
    }

    /// <summary>
    ///     返回格式为 (yyyy-MM-dd) 的时间字符串
    /// </summary>
    /// <param name="dt">要格式化的 DateTime 对象</param>
    /// <returns>格式化后的时间字符串</returns>
    public static string ToStringDate(this DateTime dt)
    {
        return dt.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
    }

    /// <summary>
    ///     返回格式为 (yyyy-MM-dd) 的时间字符串
    /// </summary>
    /// <param name="dt">要格式化的 DateTime? 对象</param>
    /// <returns>格式化后的时间字符串，如果为空则返回空字符串</returns>
    public static string ToStringDate(this DateTime? dt)
    {
        return dt?.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) ?? string.Empty;
    }

    /// <summary>
    ///     返回格式为 (yyyy-MM-dd HH:mm:ss) 的时间字符串
    /// </summary>
    /// <param name="dt">要格式化的 DateTimeOffset 对象</param>
    /// <returns>格式化后的时间字符串</returns>
    public static string ToStringLongDate(this DateTimeOffset dt)
    {
        return dt.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
    }

    /// <summary>
    ///     返回格式为 (yyyy-MM-dd HH:mm:ss) 的时间字符串
    /// </summary>
    /// <param name="dt">要格式化的 DateTimeOffset? 对象</param>
    /// <returns>格式化后的时间字符串，如果为空则返回空字符串</returns>
    public static string ToStringLongDate(this DateTimeOffset? dt)
    {
        return dt?.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) ?? string.Empty;
    }

    /// <summary>
    ///     返回格式为 (yyyy-MM-dd) 的时间字符串
    /// </summary>
    /// <param name="dt">要格式化的 DateTimeOffset 对象</param>
    /// <returns>格式化后的时间字符串</returns>
    public static string ToStringDate(this DateTimeOffset dt)
    {
        return dt.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
    }

    /// <summary>
    ///     返回格式为 (yyyy-MM-dd) 的时间字符串
    /// </summary>
    /// <param name="dt">要格式化的 DateTimeOffset? 对象</param>
    /// <returns>格式化后的时间字符串，如果为空则返回空字符串</returns>
    public static string ToStringDate(this DateTimeOffset? dt)
    {
        return dt?.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) ?? string.Empty;
    }

    

    #region DateTime To TimeStamp

    /// <summary>
    /// 获取以秒为单位的时间戳 10位
    /// </summary>
    /// <param name="dateTime"></param>
    /// <returns></returns>
    public static long ToUnixTimestamp(this DateTime dateTime)
    {
        return (long)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
    }

    /// <summary>
    /// 获取以毫秒为单位的时间戳 13位
    /// </summary>
    /// <param name="dateTime"></param>
    /// <returns></returns>
    public static long ToUnixTimestampMilliseconds(this DateTime dateTime)
    {
        return (long)(dateTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))
            .TotalMilliseconds;
    }

    /// <summary>
    /// 将 Unix 时间戳（秒）转换为 DateTime
    /// </summary>
    /// <param name="timestamp"></param>
    /// <returns></returns>
    public static DateTime FromUnixTimestamp(long timestamp)
    {
        return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(timestamp);
    }

    /// <summary>
    /// 将 Unix 时间戳（毫秒）转换为 DateTime
    /// </summary>
    /// <param name="timestamp"></param>
    /// <returns></returns>
    public static DateTime FromUnixTimestampMilliseconds(long timestamp)
    {
        return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(timestamp);
    }

    #endregion

    #region DateTimeOffset To TimeStamp

    /// <summary>
    /// 获取以秒为单位的时间戳 10位
    /// </summary>
    /// <param name="dateTimeOffset"></param>
    /// <returns></returns>
    public static long ToUnixTimestamp(this DateTimeOffset dateTimeOffset)
    {
        return (long)(dateTimeOffset - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds;
    }

    /// <summary>
    /// 获取以毫秒为单位的时间戳 13位
    /// </summary>
    /// <param name="dateTimeOffset"></param>
    /// <returns></returns>
    public static long ToUnixTimestampMilliseconds(this DateTimeOffset dateTimeOffset)
    {
        return (long)(dateTimeOffset - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalMilliseconds;
    }

    /// <summary>
    /// 将 Unix 时间戳（秒）转换为 DateTimeOffset
    /// </summary>
    /// <param name="timestamp"></param>
    /// <returns></returns>
    public static DateTimeOffset FromUnixTimestampToDateTimeOffset(long timestamp)
    {
        return new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddSeconds(timestamp);
    }

    /// <summary>
    /// 将 Unix 时间戳（毫秒）转换为 DateTimeOffset
    /// </summary>
    /// <param name="timestamp"></param>
    /// <returns></returns>
    public static DateTimeOffset FromUnixTimestampMillisecondsToDateTimeOffset(long timestamp)
    {
        return new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddMilliseconds(timestamp);
    }

    #endregion


    #region 一天的开始和结束时间

    /// <summary>
    ///     获取一天的结束时间 (23:59:59)
    /// </summary>
    /// <param name="dt">要处理的 DateTime 对象</param>
    /// <returns>一天的结束时间</returns>
    public static DateTime ToDayEndTime(this DateTime dt)
    {
        return new DateTime(dt.Year, dt.Month, dt.Day, 23, 59, 59, DateTimeKind.Utc);
    }

    /// <summary>
    ///     获取一天的结束时间 (23:59:59)
    /// </summary>
    /// <param name="dt">要处理的 DateTime? 对象</param>
    /// <returns>一天的结束时间，如果为空则返回默认值</returns>
    public static DateTime ToDayEndTime(this DateTime? dt)
    {
        return dt?.ToDayEndTime() ?? default;
    }

    /// <summary>
    ///     获取一天的开始时间 (00:00:00)
    /// </summary>
    /// <param name="dt">要处理的 DateTime 对象</param>
    /// <returns>一天的开始时间</returns>
    public static DateTime ToDayStartTime(this DateTime dt)
    {
        return new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, DateTimeKind.Utc);
    }

    /// <summary>
    ///     获取一天的开始时间 (00:00:00)
    /// </summary>
    /// <param name="dt">要处理的 DateTime? 对象</param>
    /// <returns>一天的开始时间，如果为空则返回默认值</returns>
    public static DateTime ToDayStartTime(this DateTime? dt)
    {
        return dt?.ToDayStartTime() ?? default;
    }

    /// <summary>
    ///     获取一天的结束时间 (23:59:59)
    /// </summary>
    /// <param name="dt">要处理的 DateTimeOffset 对象</param>
    /// <returns>一天的结束时间</returns>
    public static DateTimeOffset ToDayEndTime(this DateTimeOffset dt)
    {
        return new DateTimeOffset(dt.Year, dt.Month, dt.Day, 23, 59, 59, dt.Offset);
    }

    /// <summary>
    ///     获取一天的结束时间 (23:59:59)
    /// </summary>
    /// <param name="dt">要处理的 DateTimeOffset? 对象</param>
    /// <returns>一天的结束时间，如果为空则返回默认值</returns>
    public static DateTimeOffset ToDayEndTime(this DateTimeOffset? dt)
    {
        return dt?.ToDayEndTime() ?? default;
    }

    /// <summary>
    ///     获取一天的开始时间 (00:00:00)
    /// </summary>
    /// <param name="dt">要处理的 DateTimeOffset 对象</param>
    /// <returns>一天的开始时间</returns>
    public static DateTimeOffset ToDayStartTime(this DateTimeOffset dt)
    {
        return new DateTimeOffset(dt.Year, dt.Month, dt.Day, 0, 0, 0, dt.Offset);
    }

    /// <summary>
    ///     获取一天的开始时间 (00:00:00)
    /// </summary>
    /// <param name="dt">要处理的 DateTimeOffset? 对象</param>
    /// <returns>一天的开始时间，如果为空则返回默认值</returns>
    public static DateTimeOffset ToDayStartTime(this DateTimeOffset? dt)
    {
        return dt?.ToDayStartTime() ?? default;
    }

    #endregion 一天的开始和结束时间
}